using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Zune.Forms
{
    /// <summary>
    /// Zune.Forms ContextMenu control
    /// </summary>
    public class ContextMenu : Control
    {
        #region Public Event
        public event EventHandler MenuItemClicked;
        #endregion

        #region Private Members
        internal List<MenuItem> _menuItems = new List<MenuItem>();
        internal Vector2 _menItemSize = new Vector2(100, 30);
        internal SpriteFont _font;
        internal Color _pressedBackColor = Color.DarkGray;
        internal Color _pressedForeColor = Color.White;
        internal Color _disabledForeColor = Color.Silver;
        internal Vector2 _lastTouchPos;
        internal Control _parent;
        internal System.Threading.Timer _touchTimer;
        #endregion

        #region Constructors
        /// <summary>
        /// Creates a new ContextMenu control
        /// </summary>
        /// <param name="parent"></param>
        public ContextMenu(Control parent) : base(parent)
        {
            base.Size = new Vector2(100, 30);
            base.BackColor = Color.LightGray;
            base.ForeColor = Color.Black;
            base.Visible = false;
            base._form._sysControls.Add(this);
            _parent = parent;
            _parent.ControlTouched -= new OnControlTouched(parent_ControlTouching);
            _parent.ControlTouched += new OnControlTouched(parent_ControlTouched);
            _parent.ControlTouchReleased += new OnControlTouched(parent_ControlTouchReleased);
            _parent.LostFocus += new OnControlTouched(_parent_LostFocus);
            _touchTimer = new System.Threading.Timer(_touchTimer_Tick, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            base._borderType = Enumerations.BorderType.Border3D;
        }

        internal ContextMenu(Form form) : base(form)
        {
            base.Size = new Vector2(100, 30);
            base.BackColor = Color.LightGray;
            base.ForeColor = Color.Black;
            base.Visible = false;
            _touchTimer = new System.Threading.Timer(_touchTimer_Tick, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            base._borderType = Enumerations.BorderType.Border3D;
        }
        #endregion

        #region Private Event Handlers
        protected void _parent_LostFocus(object sender, GameTime gameIime, TouchLocation touch)
        {
            _touchTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            ((Control)_parent).ControlTouched -= new OnControlTouched(parent_ControlTouching);
            ((Control)_parent).ControlTouched += new OnControlTouched(parent_ControlTouched);
            if (!Utilities.IsControlTouched(touch.Position, _location, _size))
            {
                Visible = false;
            }
        }

        protected void _touchTimer_Tick(object obj)
        {
            ((Control)_parent).ControlTouched -= new OnControlTouched(parent_ControlTouching);
            ((Control)_parent).ControlTouched += new OnControlTouched(parent_ControlTouched);
            _touchTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            _location = new Vector2(_lastTouchPos.X - (_size.X / 2), _parent.Bottom + 1);
            float y = _location.Y + 1;
            foreach (MenuItem menuItem in _menuItems)
            {
                Vector2 tmpSize = _font.MeasureString(menuItem.Text);
                if (tmpSize.X > _size.X)
                    Size = new Vector2(tmpSize.X + 15, y);

                if (tmpSize.Y > _menItemSize.Y)
                    _menItemSize = new Vector2(_menItemSize.X, tmpSize.Y);

                menuItem._location = new Vector2(Left + 5, y);
                y += _menItemSize.Y;
            }
            Size = new Vector2(Size.X, (_menuItems.Count * _menItemSize.Y) + 6);

            if (Utilities.IsControlTouched(_lastTouchPos, _parent._location, _parent._size) && _parent.Visible)
            {
                Visible = true;
            }
        }

        protected void parent_ControlTouchReleased(object sender, GameTime gameTime, TouchLocation touch)
        {
            _touchTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            ((Control)_parent).ControlTouched -= new OnControlTouched(parent_ControlTouching);
            ((Control)_parent).ControlTouched += new OnControlTouched(parent_ControlTouched);
        }

        protected void parent_ControlTouched(object sender, GameTime gameTime, TouchLocation touch)
        {
            if (!_visible)
            {
                ((Control)_parent).ControlTouched -= new OnControlTouched(parent_ControlTouched);
                ((Control)_parent).ControlTouched += new OnControlTouched(parent_ControlTouching);
                _touchTimer.Change(_parent._contextMenuDelay, System.Threading.Timeout.Infinite);
            }
        }

        protected void parent_ControlTouching(object sender, GameTime gameTime, TouchLocation touch)
        {
            _lastTouchPos = touch.Position;
        }

        protected void menuItem_Clicked(object sender, EventArgs e)
        {
            _visible = false;
            if (MenuItemClicked != null)
                MenuItemClicked(sender, e);
        }
        #endregion

        #region Public Overrides
        public override void LoadContent()
        {
            _font = _form.Content.Load<SpriteFont>("DefaultFont");

            foreach (MenuItem menuItem in _menuItems)
            {
                menuItem.LoadContent();
                menuItem.Clicked += new EventHandler(menuItem_Clicked);
            }
            base.LoadContent();
        }

        public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            if (_visible)
            {
                Texture2D _mainBack = Drawing.CreateRectangle(_form.GraphicsDevice, (Int32)Size.X + 10, (Int32)Size.Y + 5, _backColor);
                Texture2D _pressedBackround = Drawing.CreateRectangle(_form.GraphicsDevice, (Int32)_menItemSize.X - 10, (Int32)_menItemSize.Y, _pressedBackColor);
                Texture2D _background = Drawing.CreateRectangle(_form.GraphicsDevice, (Int32)_menItemSize.X - 10, (Int32)_menItemSize.Y, _backColor);

                base.Draw(gameTime);

                foreach (MenuItem menuItem in _menuItems)
                {
                    menuItem.Draw(gameTime, _background, _pressedBackround);
                }
                
               
            }
        }

        public override void Update(Microsoft.Xna.Framework.GameTime gameTime, Microsoft.Xna.Framework.Input.TouchCollection touches)
        {
            if (_visible)
            {
                if (touches.Count > 0)
                {
                    TouchLocation touch = touches[0];
                    foreach (MenuItem menuItem in _menuItems)
                        menuItem.Update(gameTime, touch);
                }
                base.Update(gameTime, touches);
            }
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets or sets the MenuItems to use for the ContextMenu
        /// </summary>
        public List<MenuItem> MenuItems
        {
            get { return _menuItems; }
            set { _menuItems = value; }
        }

        /// <summary>
        /// Gets or sets the Size of the ContextMenu.
        /// </summary>
        public new Vector2 Size
        {
            get { return _size; }
            set 
            {
                _size = value;
                _menItemSize = new Vector2(_size.X-2, _menItemSize.Y);
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns a MenuItem based on the text of the MenuItem.
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public MenuItem FindMenuItemByText(string text)
        {
            foreach (MenuItem mi in _menuItems)
            {
                if (mi.Text == text)
                    return mi;
            }

            return null;
        }
        #endregion
    }
}